package org.zoomdev.zoom.aop.utils;

import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.zoomdev.zoom.ioc.annotations.IocBean;
import org.zoomdev.zoom.ioc.annotations.ModuleInit;

import java.util.List;

import static org.objectweb.asm.Opcodes.ASM9;
import static org.objectweb.asm.Opcodes.NEW;

public class ScanModuleVisitor extends ClassVisitor {

    private static final String IOC_BEAN = Type.getDescriptor(IocBean.class);
    private static final String MODULE_INIT = Type.getDescriptor(ModuleInit.class);
    private final String className;
    IocBeanConfig currentBeanConfig;

    private final List<BaseMethodConfig> configs ;

    protected ScanModuleVisitor(String className, List<BaseMethodConfig> configs) {
        super(ASM9);
        this.className = className;
        this.configs = configs;
    }


    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        super.visit(version, access, name, signature, superName, interfaces);
    }

    @Override
    public MethodVisitor visitMethod(int access, String methodName, String methodDesc, String signature, String[] exceptions) {
        //System.out.println("visit method:" + name + "====> " + descriptor);

        if (methodName.equals("<init>")) {
            return super.visitMethod(access, methodName, methodDesc, signature, exceptions);
        }

        MethodVisitor mv = super.visitMethod(access, methodName, methodDesc, signature, exceptions);

        System.out.println(methodName + "" + methodDesc);
        return new MethodVisitor(api, mv) {

            @Override
            public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
                System.out.println(descriptor);
                AnnotationVisitor v = super.visitAnnotation(descriptor, visible);
                if (descriptor.equals(IOC_BEAN)) {
                    IocBeanConfig config = new IocBeanConfig();
                    config.setMethod(methodName);
                    config.setClassName(className);
                    config.setDesc(methodDesc);
                    configs.add(config);
                    currentBeanConfig = config;
                    return new AnnotationVisitor(api, v) {
                        @Override
                        public void visit(String name, Object value) {
                            if (name.equals("name")) {
                                config.setName((String) value);
                            }
                            super.visit(name, value);
                        }
                    };
                } else if (descriptor.equals(MODULE_INIT)) {
                    ModuleInitConfig config = new ModuleInitConfig();
                    config.setMethod(methodName);
                    config.setClassName(className);
                    config.setDesc(methodDesc);
                    configs.add(config);
                    return new AnnotationVisitor(api, v) {
                        @Override
                        public void visit(String name, Object value) {
                            if (name.equals("async")) {
                                config.setAsync((Boolean) value);
                            } else if (name.equals("after")) {
                                config.setAfter((Boolean) value);
                            }
                            super.visit(name, value);
                        }
                    };
                }
                return v;
            }


            @Override
            public void visitTypeInsn(int opcode, String type) {
                if (opcode == NEW) {
                    //map.put(name,type);
                    currentBeanConfig.setNewOp(type);
                }
                super.visitTypeInsn(opcode, type);
            }


        };
    }

}
